(ns com.ufo5260987423.graphDatabase.core.clojure.apis.basic
  (:use com.ufo5260987423.graphDatabase.core.clojure.core.utils)
  (:use com.ufo5260987423.graphDatabase.core.clojure.core.gao)
  (:use com.ufo5260987423.graphDatabase.core.clojure.core.client)
  (:use com.ufo5260987423.graphDatabase.core.clojure.core.route)
  (:use clojure.data))

(defn get-node [id]
  (write-with-reply
    (get-conn (route (graph-node id nil nil nil) servers))
    (list 'get-graph-node-by id)))

(defn save-consistent-graph-node [graph-node]
  (save-graph-node
    (if (graph-node-is-raw? graph-node)
      (conj graph-node
        {:graph-node-id (get-consistent-graph-node-id servers (first (first (filter #(= (second %) local) connector-pool))))})
      graph-node)))

(defn search-graph-node-by [attribute-name attribute-value]
  (vec (reduce #(reduce conj %1 %2)
    ()
    (map
      #(write-with-reply %
         (list 'search-node-by-attribute attribute-name attribute-value))
      (vals connector-pool)))))

(defn save-node [graph-node]
  (let [graph-node-old (get-node (:graph-node-id graph-node))
        old-from-this-node-edges
        (first (diff (:from-this-node-edges-map graph-node-old) (:from-this-node-edges-map graph-node)))
        new-from-this-node-edges
        (second (diff (:from-this-node-edges-map graph-node-old) (:from-this-node-edges-map graph-node)))
        old-to-this-node-edges
        (first (diff (:to-this-node-edges-map graph-node-old) (:to-this-node-edges-map graph-node)))
        new-to-this-node-edges
        (second (diff (:to-this-node-edges-map graph-node-old) (:to-this-node-edges-map graph-node)))]
    (map
      #(write-with-reply
         (get-conn (route (graph-node (:to-node-id %) nil nil nil) servers))
         (list 'save-graph-edge %))
      new-from-this-node-edges)
    (map
      #(if (not (contain-node-id-in-graph-edge-map? (:to-node-id %) new-to-this-node-edges :to-node-id))
         (write-with-reply
           (get-conn (route (graph-node (:to-node-id %) nil nil nil) servers))
           (list 'delete-graph-edge (:from-node-id %) (:to-node-id %))))
      old-from-this-node-edges)
    (map
      #(write-with-reply
         (get-conn (route (graph-node (:from-node-id %) nil nil nil) servers))
         (list 'save-graph-edge %))
      new-to-this-node-edges)
    (map
      #(if (not (contain-node-id-in-graph-edge-map? (:from-node-id %) new-to-this-node-edges :from-node-id))
         (write-with-reply
           (get-conn (route (graph-node (:from-node-id %) nil nil nil) servers))
           (list 'delete-graph-edge (:from-node-id %) (:to-node-id %))))
      old-from-this-node-edges)

    (write-with-reply
      (get-conn (route graph-node servers))
      (list 'save-consistent-graph-node graph-node))))

(defn delete-node [graph-node-id]
  (let [graph-node (get-node graph-node-id)]
    (do
      (map
        #(write-with-reply
           (get-conn (route (graph-node % nil nil nil) servers))
           (list 'delete-graph-edge graph-node-id %))
        (get-related-graph-node-id (:from-this-node-edges-map graph-node) :to-node-id))

      (map
        #(write-with-reply
           (get-conn (route (graph-node % nil nil nil) servers))
           (list 'delete-graph-edge % graph-node-id))
        (get-related-graph-node-id (:to-this-node-edges-map graph-node) :from-node-id))

      (write-with-reply
        (get-conn (route (graph-node graph-node-id nil nil nil) servers))
        (list 'delete-graph-node graph-node)))))

(defn save-edge [graph-edge]
  {(:from-node-id graph-edge)
   (write-with-reply
     (get-conn (route (graph-node (:from-node-id graph-edge) nil nil nil) servers))
     (list 'save-graph-edge graph-edge))

   (:to-node-id graph-edge)
   (write-with-reply
     (get-conn (route (graph-node (:to-node-id graph-edge) nil nil nil) servers))
     (list 'save-graph-edge graph-edge))})
